<script setup lang="ts">
import { onMounted, ref } from 'vue';

import { useAccessStore } from '@vben/stores';

import { Alert, Button, Card, Select, Spin } from 'ant-design-vue';
import { BookOpen, Download, RefreshCw, Server, Shield } from 'lucide-vue-next';
// 动态导入 swagger-ui-dist
// @ts-ignore
import SwaggerUIBundle from 'swagger-ui-dist/swagger-ui-bundle.js';

import { requestClient } from '#/api/request';

import 'swagger-ui-dist/swagger-ui.css';

// 定义服务列表
interface ServiceConfig {
  name: string;
  label: string;
  apiDocsUrl: string;
  proxyUrl: string;
  description: string;
}

const services: ServiceConfig[] = [
  {
    name: 'system',
    label: '系统服务中心',
    apiDocsUrl: '/system/v3/api-docs',
    proxyUrl: '/api/system',
    description: '用户、角色、菜单、权限等系统管理接口',
  },
  {
    name: 'auth',
    label: '授权服务中心',
    apiDocsUrl: '/auth/v3/api-docs',
    proxyUrl: '/api/auth',
    description: 'OAuth2 认证授权相关接口',
  },
  {
    name: 'workflow',
    label: '工作流服务中心',
    apiDocsUrl: '/workflow/v3/api-docs',
    proxyUrl: '/api/workflow',
    description: '工作流服务中心相关接口',
  },
];

const currentService = ref<string>('system');
const loading = ref(true);
const error = ref('');
const apiInfo = ref<any>(null);
const swaggerUI = ref<any>(null);

// 获取当前选中的服务配置
const getCurrentServiceConfig = (): ServiceConfig => {
  return services.find((s) => s.name === currentService.value) || services[0];
};

// 加载 API 文档
const loadApiDoc = async () => {
  try {
    loading.value = true;
    error.value = '';

    const accessStore = useAccessStore();
    const token = accessStore.accessToken;

    console.log('=== 加载 API 文档 ===');
    console.log('Token:', token ? `${token.substring(0, 20)}...` : 'null');

    if (!token) {
      error.value = '未获取到认证令牌，请重新登录';
      loading.value = false;
      return;
    }

    const serviceConfig = getCurrentServiceConfig();
    console.log('服务配置:', serviceConfig);
    console.log('请求 URL:', serviceConfig.apiDocsUrl);

    // 1. 请求后端 OpenAPI 文档数据（显式添加 Authorization 头）
    const openApiData = await requestClient.get(serviceConfig.apiDocsUrl, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });
    console.log('OpenAPI 数据加载成功');
    // 验证 OpenAPI 数据
    if (!openApiData || typeof openApiData !== 'object') {
      throw new Error('OpenAPI 数据不是有效的对象');
    }

    if (!openApiData.openapi && !openApiData.swagger) {
      throw new Error(
        `缺少 openapi 或 swagger 字段。当前字段: ${Object.keys(openApiData).join(', ')}`,
      );
    }

    // 保存 API 信息
    apiInfo.value = {
      title: openApiData.info?.title || 'API 文档',
      version: openApiData.info?.version || '1.0.0',
      description: openApiData.info?.description || '',
      serverUrl: openApiData.servers?.[0]?.url || '',
      pathCount: Object.keys(openApiData.paths || {}).length,
      serviceName: serviceConfig.label,
    };

    // 2. 修改 OpenAPI 数据中的 servers，使用前端代理
    const modifiedOpenApiData = {
      ...openApiData,
      servers: [
        {
          url: serviceConfig.proxyUrl,
          description: '开发环境（通过代理）',
        },
      ],
    };

    // 3. 配置 swagger-ui
    swaggerUI.value = SwaggerUIBundle({
      dom_id: '#swagger-ui',
      spec: modifiedOpenApiData,
      deepLinking: true,
      displayRequestDuration: true, // 显示请求耗时
      filter: true, // 启用搜索过滤
      tryItOutEnabled: true, // 默认启用 Try it out
      persistAuthorization: true, // 持久化认证信息
      // 请求拦截器：为所有 API 测试请求添加 Authorization 头
      requestInterceptor: (req: any) => {
        req.headers.Authorization = `Bearer ${token}`;
        return req;
      },
      // 响应拦截器：记录响应信息
      responseInterceptor: (res: any) => {
        return res;
      },
    });

    loading.value = false;
  } catch (error_: any) {
    console.error('加载 API 文档失败:', error_);
    error.value = error_.message || '加载文档时发生错误';
    loading.value = false;
  }
};

// 切换服务
const handleServiceChange = (serviceName: string) => {
  currentService.value = serviceName;
  loadApiDoc();
};

// 下载 OpenAPI JSON
const downloadOpenApiJson = async () => {
  try {
    const accessStore = useAccessStore();
    const token = accessStore.accessToken;
    const serviceConfig = getCurrentServiceConfig();

    const openApiData = await requestClient.get(serviceConfig.apiDocsUrl, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    const blob = new Blob([JSON.stringify(openApiData, null, 2)], {
      type: 'application/json',
    });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `openapi-${serviceConfig.name}-${Date.now()}.json`;
    a.click();
    URL.revokeObjectURL(url);
  } catch (error_: any) {
    console.error('下载失败:', error_);
  }
};

// 刷新文档
const refreshDoc = () => {
  loadApiDoc();
};

onMounted(() => {
  loadApiDoc();
});
</script>

<template>
  <div class="swagger-container">
    <!-- 服务选择器 -->
    <Card class="service-selector-card mb-4">
      <div class="flex items-center justify-between">
        <div class="flex items-center gap-3">
          <Server :size="20" class="text-blue-500" />
          <span class="text-sm font-medium">选择服务：</span>
          <Select
            v-model:value="currentService"
            style="width: 200px"
            @change="handleServiceChange"
          >
            <Select.Option
              v-for="service in services"
              :key="service.name"
              :value="service.name"
            >
              {{ service.label }}
            </Select.Option>
          </Select>
        </div>
        <div class="text-xs text-gray-500">
          {{ getCurrentServiceConfig().description }}
        </div>
      </div>
    </Card>

    <!-- 顶部信息卡片 -->
    <Card v-if="!loading && !error && apiInfo" class="info-card mb-4">
      <div class="flex items-center justify-between">
        <div class="flex items-center gap-3">
          <div class="icon-wrapper">
            <BookOpen :size="24" class="text-blue-500" />
          </div>
          <div>
            <h2 class="mb-1 text-base font-semibold">
              {{ apiInfo.serviceName }} - {{ apiInfo.title }}
            </h2>
            <div class="flex items-center gap-4 text-xs text-gray-600">
              <span class="flex items-center gap-1">
                <Shield :size="12" />
                版本: {{ apiInfo.version }}
              </span>
              <span class="flex items-center gap-1">
                <Server :size="12" />
                接口数量: {{ apiInfo.pathCount }}
              </span>
            </div>
          </div>
        </div>
        <div class="flex gap-2">
          <Button type="default" @click="refreshDoc">
            <template #icon>
              <RefreshCw :size="16" />
            </template>
            刷新
          </Button>
          <Button type="primary" @click="downloadOpenApiJson">
            <template #icon>
              <Download :size="16" />
            </template>
            下载 JSON
          </Button>
        </div>
      </div>
      <div v-if="apiInfo.description" class="mt-2 text-xs text-gray-600">
        {{ apiInfo.description }}
      </div>
    </Card>

    <!-- 使用提示 -->
    <Alert
      v-if="!loading && !error"
      message="使用提示"
      description="所有 API 请求已自动携带认证 Token，您可以直接点击 'Try it out' 按钮测试接口。"
      type="info"
      show-icon
      closable
      class="mb-4"
    />

    <!-- 加载中提示 -->
    <div v-if="loading" class="loading">
      <Spin size="large" tip="正在加载 API 文档..." />
    </div>

    <!-- 错误提示 -->
    <Card v-if="error" class="error-card">
      <div class="error-content">
        <div class="mb-4 text-sm font-medium text-red-500">
          ❌ {{ error }}
        </div>
        <div class="flex justify-center gap-2">
          <Button type="primary" @click="refreshDoc">重试</Button>
          <Button
            type="default"
            @click="() => (window.location.href = '/login')"
          >
            返回登录
          </Button>
        </div>
      </div>
    </Card>

    <!-- swagger-ui 容器 -->
    <div id="swagger-ui" :class="{ hidden: loading || error }"></div>
  </div>
</template>

<style scoped>
.swagger-container {
  width: 100%;
  min-height: 100vh;
  padding: 20px;
  box-sizing: border-box;
  background: #f5f7fa;
}

.service-selector-card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.service-selector-card :deep(.ant-card-body) {
  padding: 16px 24px;
}

.info-card {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border: none;
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.info-card :deep(.ant-card-body) {
  padding: 24px;
}

.icon-wrapper {
  width: 48px;
  height: 48px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(10px);
}

.info-card h2 {
  color: white;
  margin: 0;
}

.info-card .text-gray-600 {
  color: rgba(255, 255, 255, 0.9) !important;
}

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 100px;
  font-size: 14px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.error-card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.error-content {
  text-align: center;
  padding: 50px;
}

.mb-4 {
  margin-bottom: 16px;
}

/* 自定义 swagger-ui 样式 */
#swagger-ui {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  font-size: 13px; /* 全局字体大小 */
}

:deep(.swagger-ui .topbar) {
  display: none; /* 隐藏默认顶栏，使用自定义顶栏 */
}

:deep(.swagger-ui .info) {
  margin: 0;
}

:deep(.swagger-ui .info .title) {
  color: #333;
  font-size: 18px;
  margin-bottom: 8px;
  font-weight: 600;
}

:deep(.swagger-ui .info .description) {
  color: #666;
  font-size: 13px;
}

:deep(.swagger-ui .scheme-container) {
  background: #f8f9fa;
  padding: 15px;
  border-radius: 6px;
  margin: 20px 0;
}

:deep(.swagger-ui .opblock-tag) {
  border-bottom: 2px solid #667eea;
  margin: 20px 0;
}

:deep(.swagger-ui .opblock-tag-section) {
  margin-bottom: 20px;
}

:deep(.swagger-ui .opblock) {
  border-radius: 6px;
  margin-bottom: 10px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

:deep(.swagger-ui .opblock.opblock-get) {
  border-color: #61affe;
  background: rgba(97, 175, 254, 0.05);
}

:deep(.swagger-ui .opblock.opblock-post) {
  border-color: #49cc90;
  background: rgba(73, 204, 144, 0.05);
}

:deep(.swagger-ui .opblock.opblock-put) {
  border-color: #fca130;
  background: rgba(252, 161, 48, 0.05);
}

:deep(.swagger-ui .opblock.opblock-delete) {
  border-color: #f93e3e;
  background: rgba(249, 62, 62, 0.05);
}

:deep(.swagger-ui .btn.execute) {
  background: #667eea;
  border-color: #667eea;
}

:deep(.swagger-ui .btn.execute:hover) {
  background: #5568d3;
  border-color: #5568d3;
}

:deep(.swagger-ui .response-col_status) {
  font-weight: bold;
}

:deep(.swagger-ui .response-col_status.response-200) {
  color: #49cc90;
}

:deep(.swagger-ui .response-col_status.response-400),
:deep(.swagger-ui .response-col_status.response-404),
:deep(.swagger-ui .response-col_status.response-500) {
  color: #f93e3e;
}

/* 搜索框样式 */
:deep(.swagger-ui .filter-container) {
  margin-bottom: 20px;
}

:deep(.swagger-ui .filter-container input) {
  border-radius: 6px;
  border: 1px solid #d9d9d9;
  padding: 8px 12px;
}

:deep(.swagger-ui .filter-container input:focus) {
  border-color: #667eea;
  box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2);
}

/* 调整标签和分组标题大小 */
:deep(.swagger-ui .opblock-tag) {
  font-size: 16px;
  font-weight: 600;
}

:deep(.swagger-ui .opblock-summary-description) {
  font-size: 13px;
}

:deep(.swagger-ui .opblock-summary-path) {
  font-size: 13px;
}

:deep(.swagger-ui .opblock-summary-method) {
  font-size: 12px;
  min-width: 60px;
}

/* 调整参数和响应表格字体 */
:deep(.swagger-ui table thead tr th) {
  font-size: 12px;
}

:deep(.swagger-ui table tbody tr td) {
  font-size: 13px;
}

/* 调整模型字体 */
:deep(.swagger-ui .model-title) {
  font-size: 14px;
}

:deep(.swagger-ui .model) {
  font-size: 13px;
}

/* 调整按钮字体 */
:deep(.swagger-ui .btn) {
  font-size: 13px;
  padding: 6px 16px;
}

/* 调整代码块字体 */
:deep(.swagger-ui .highlight-code) {
  font-size: 12px;
}

:deep(.swagger-ui .microlight) {
  font-size: 12px;
}

/* 调整响应状态码字体 */
:deep(.swagger-ui .response-col_status) {
  font-size: 13px;
}

/* 调整描述文字 */
:deep(.swagger-ui .markdown p) {
  font-size: 13px;
}

:deep(.swagger-ui .renderedMarkdown p) {
  font-size: 13px;
}
</style>
